﻿using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;

namespace NazTek.Extension.Clr4
{
    /// <summary>
    /// Gets a list of custom attributes asociated with an enum item
    /// </summary>
    public sealed class DescriptionAttributeList : List<DescriptionAttribute>
    {
        /// <summary>
        /// Extracts all custom attributes from the specified enum item and hydrates the composite list
        /// </summary>
        /// <param name="enumValue">The enum item to extract custom attributes from</param>
        internal DescriptionAttributeList(Enum enumValue)
        {
            Type enumType = enumValue.GetType();
            FieldInfo fieldInfo = enumType.GetField(Enum.GetName(enumType, enumValue), BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public | BindingFlags.NonPublic);
            object[] descriptions = fieldInfo.GetCustomAttributes(false);
            if (descriptions != null)
                descriptions.ToList().ForEach(description => Add(description as DescriptionAttribute));
        }
        /// <summary>
        /// Gets the first matching custom attribute's value for the specified conditions
        /// </summary>
        /// <param name="descriptionId">The key to search for in the list</param>
        /// <param name="defaultEnumValue">The value to return when no match is found</param>
        /// <returns>Matched description value or the specified default value when no match is found</returns>
        public string GetDescription(string descriptionId = null, string defaultEnumValue = null)
        {
            if (string.IsNullOrWhiteSpace(descriptionId))
            {
                DescriptionAttribute keylessDescription = this.SingleOrDefault(descr => descr.HasKey == false);
                return keylessDescription == null ? defaultEnumValue : keylessDescription.DescriptionText;
            }
            DescriptionAttribute keyedDescription = this.SingleOrDefault(descr => descr.DescriptionId == descriptionId);
            return keyedDescription == null ? defaultEnumValue : keyedDescription.DescriptionText;
        }
        /// <summary>
        /// Gets whether the list contains the specified description value
        /// </summary>
        /// <param name="enumItemDescription">The description value to match</param>
        /// <returns>True when a match is found, otherwise false</returns>
        internal bool ContainsDescription(string enumItemDescription)
        {
            return this.SingleOrDefault(desc => desc.DescriptionText == enumItemDescription) != null;
        }
    }
}